
# generating files for cmds
# primarily support C++

import os
import subprocess
import shutil

from xml.dom import minidom

basedir = os.path.dirname(__file__)
gens = [{
        'cmds': 'cmds.xml',
        'src': '../../C++/app/demo/src/',
        'namespace': 'anb::app::demo::handler',
        'dispatcher': 'dispatcher',
    }]

def ensure_dir(d):
    try:
        os.makedirs(d)
    except:
        pass

def save_file(path, text):
    f = open(path, 'w')
    try:
        f.write(text)
    finally:
        f.close()

dispatcher_h_format = """/// AUTO-GENERATED, do not edit

#include <anb/net/dispatcher.h>

${ns_pre}

class ${dispatcher} : public anb::net::dispatcher {
public:
protected:
private:
}

${ns_post}
"""

dispatcher_cpp_format = """/// AUTO-GENERATED, do not edit

#include "${dispatcher}.h"

${ns_pre}

${dispatcher}::${dispatcher}() : anb::net::dispatcher() {
}

${dispatcher}::~${dispatcher}() {
}

${ns_post}
"""

for gen in gens:
    xml = os.path.join(basedir, gen['cmds'])
    xmldoc = minidom.parse(xml)
    root = xmldoc.documentElement

    sizeLimit = root.attributes.get('size-limit')
    if not sizeLimit:
        print("root size-limit not defined, use default 500K")
        sizeLimit = '500K'


    classes = {}

    cmds = root.getElementsByTagName('cmd')
    for cmd in cmds:
        attrs = cmd.attributes

        name = attrs.get('name')
        id_ = attrs.get('id')
        sizeLimit_ = attrs.get('size-limit')
        if not sizeLimit_:
            sizeLimit_ = sizeLimit

        if not name:
            print("cmd without name, exit");
            exit(-1);
        if not id_:
            print("cmd without id, exit");
            exit(-1);

        name = name.value
        id_ = id_.value
        sizeLimit_ = sizeLimit_.value

        splits = name.split('.')
        if len(splits) != 2:
            print("cmd name " + name + " not valid, exit");
            exit(-1);

        className = splits[0]
        methodName = splits[1]

        clazz = classes.get(className)
        if not clazz:
            classes[className] = clazz = {
                    'name': className,
                    'methods': {}
                    }

        methods = clazz['methods']
        method = methods.get(methodName)
        if not method:
            methods[methodName] = method = {
                    'id': id_,
                    'name': methodName,
                    'in': attrs.get('in'),
                    'out': attrs.get('out'),
                    'size-limit': sizeLimit_,
                    }
    #
    src_basedir = os.path.join(basedir, gen['src'])
    ns = gen['namespace'];
    ns_splits = ns.split('::');
    srcdir = os.path.join(src_basedir, '/'.join(ns_splits))
    ensure_dir(srcdir)

    ns_pre  = ["namespace " + split + " {" for split in ns_splits]
    ns_post = ["}" for split in ns_splits]

    dispatcher = gen['dispatcher']
    dispatcher_h = os.path.join(srcdir, dispatcher + '.h')
    dispatcher_cpp = os.path.join(srcdir, dispatcher + '.cpp')

    text = dispatcher_h_format
    text = text.replace('${ns_pre}' , ' '.join(ns_pre) )
    text = text.replace('${ns_post}', ' '.join(ns_post))
    text = text.replace('${dispatcher}', dispatcher)
    save_file(dispatcher_h, text)

    text = dispatcher_cpp_format
    text = text.replace('${ns_pre}' , ' '.join(ns_pre) )
    text = text.replace('${ns_post}', ' '.join(ns_post))
    text = text.replace('${dispatcher}', dispatcher)
    save_file(dispatcher_cpp, text)




